/**
 * Vue CLI 配置文件
 * 该文件用于配置项目的构建、开发服务器和其他相关功能
 */
const { defineConfig } = require("@vue/cli-service");
const path = require("path");
const CompressionPlugin = require("compression-webpack-plugin"); // Gzip压缩插件，用于减小打包体积
const TerserPlugin = require("terser-webpack-plugin"); // JS压缩插件，用于优化JS代码
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin"); // CSS压缩插件，用于优化CSS代码

// 判断是否为生产环境，根据环境变量NODE_ENV的值来确定
const isProduction = process.env.NODE_ENV === "production";

module.exports = defineConfig({
    /**
     * 基本路径 - 部署应用包时的基本URL
     * 如果是生产环境，可以改为 './' 以使用相对路径，方便部署到任意路径
     * 默认为 '/'，适用于部署在域名根路径的情况
     */
    publicPath: "/",

    /**
     * 输出文件目录 - 打包后的文件将放在此目录下
     * 默认为 'dist'，可根据需要修改
     */
    outputDir: "dist",

    /**
     * 静态资源目录 - 放置生成的静态资源(js、css、img、fonts)的目录
     * 相对于outputDir
     */
    assetsDir: "static",

    /**
     * 指定生成的 index.html 的输出路径，相对于 outputDir
     * 默认为 'index.html'
     */
    indexPath: "index.html",

    /**
     * 文件名哈希 - 控制打包后文件名是否包含哈希值
     * 用于缓存控制，当文件内容变化时，文件名也会变化，浏览器就会重新加载
     */
    filenameHashing: true,

    /**
     * 生产环境是否生成 sourceMap 文件
     * sourceMap用于调试，但会增加构建时间和文件大小
     * 设为false可加速生产环境构建
     */
    productionSourceMap: false,

    /**
     * 是否在开发环境下通过 eslint-loader 在每次保存时 lint 代码
     * 生产环境下不进行lint，以提高构建速度
     */
    lintOnSave: process.env.NODE_ENV !== "production",

    /**
     * webpack配置 - 可以是对象或函数
     * 这里使用函数形式，可以根据环境变量进行不同配置
     * @param {Object} config - webpack配置对象
     */
    configureWebpack: config => {
        /**
         * 配置解析别名 - 简化模块引入路径
         * 例如：import '@/components/Button' 代替 import 'src/components/Button'
         */
        config.resolve.alias = {
            ...config.resolve.alias,
            "@": path.resolve(__dirname, "src"), // 项目根目录
            "@components": path.resolve(__dirname, "src/components"), // 组件目录
            "@views": path.resolve(__dirname, "src/views"), // 页面目录
            "@assets": path.resolve(__dirname, "src/assets"), // 资源目录
            "@utils": path.resolve(__dirname, "src/utils"), // 工具函数目录
            "@store": path.resolve(__dirname, "src/store"), // 状态管理目录
            "@api": path.resolve(__dirname, "src/api") // API接口目录
        };

        /**
         * 性能提示 - 关闭webpack的性能提示
         * 避免因文件过大而产生的警告
         */
        config.performance = {
            hints: false
        };

        /**
         * 生产环境特殊配置
         * 只在生产环境下应用的优化配置
         */
        if (isProduction) {
            /**
             * 添加Gzip压缩插件
             * 将大文件压缩，减少传输体积，提高加载速度
             */
            config.plugins.push(
                new CompressionPlugin({
                    algorithm: "gzip", // 压缩算法
                    test: /\.(js|css|html|svg)$/, // 匹配需要压缩的文件类型
                    threshold: 10240, // 只处理大于10KB的资源
                    minRatio: 0.8, // 只有压缩率小于0.8的资源才会被处理
                    deleteOriginalAssets: false // 保留原始文件，不删除
                })
            );

            /**
             * 优化分包 - 将第三方库单独打包
             * 利用浏览器缓存机制，提高加载速度
             */
            config.optimization = {
                ...config.optimization,
                splitChunks: {
                    chunks: "all", // 所有模块都进行分割
                    cacheGroups: {
                        vendor: {
                            name: "chunk-vendors", // 第三方库，如node_modules中的模块
                            test: /[\\/]node_modules[\\/]/,
                            priority: 10, // 优先级，数字越大优先级越高
                            chunks: "initial" // 只对入口文件处理
                        },
                        common: {
                            name: "chunk-common", // 公共模块，被多个地方引用的代码
                            minChunks: 2, // 至少被引用2次才会被提取
                            priority: 5, // 优先级
                            reuseExistingChunk: true // 重用已存在的块，避免重复打包
                        }
                    }
                },
                /**
                 * 压缩配置 - 优化代码体积
                 * 使用TerserPlugin压缩JS，CssMinimizerPlugin压缩CSS
                 */
                minimizer: [
                    new TerserPlugin({
                        terserOptions: {
                            compress: {
                                drop_console: true, // 生产环境去除console语句
                                drop_debugger: true // 生产环境去除debugger语句
                            }
                        },
                        parallel: true // 使用多进程并行运行提高构建速度
                    }),
                    new CssMinimizerPlugin() // 压缩CSS
                ]
            };
        }
    },

    /**
     * 对内部的 webpack 配置进行更细粒度的修改
     * 比configureWebpack更灵活，可以链式调用
     * @param {Object} config - webpack链式配置
     */
    chainWebpack: config => {
        /**
         * 设置HTML页面标题
         * 修改HtmlWebpackPlugin的配置
         */
        config.plugin("html").tap(args => {
            args[0].title = "小红书"; // 设置网页标题
            return args;
        });

        /**
         * 设置预加载
         * 配置资源预加载，提高首屏加载速度
         */
        // 确保preload插件存在后再配置
        if (config.plugins.store.get('preload')) {
            config.plugin("preload").tap(() => [
                {
                    rel: "preload", // 预加载关系
                    fileBlacklist: [/\.map$/, /hot-update\.js$/], // 不预加载的文件类型
                    include: "initial" // 包含的范围
                }
            ]);
        }

        /**
         * 移除 prefetch 插件
         * prefetch会预取所有资源，可能会浪费带宽
         * 这里移除它以减少带宽压力
         */
        config.plugins.delete("prefetch");

        /**
         * 图片压缩
         * 使用image-webpack-loader压缩图片，减小体积
         * 暂时禁用，因为缺少依赖模块
         */
        /*
        config.module
            .rule("images")
            .use("image-webpack-loader")
            .loader("image-webpack-loader")
            .options({
                bypassOnDebug: true // 开发环境下跳过压缩
            })
            .end();
        */

        /**
         * 生产环境配置
         * 只在生产环境下应用的优化
         */
        if (isProduction) {
            /**
             * 移除console.log
             * 通过terser插件配置移除生产环境中的console.log
             */
            config.optimization.minimizer("terser").tap(args => {
                args[0].terserOptions.compress.drop_console = true;
                return args;
            });
        }
    },

    /**
     * CSS相关配置
     * 控制CSS的处理方式
     */
    css: {
        /**
         * 是否使用css分离插件
         * 生产环境下将CSS提取到单独的文件，提高加载性能
         */
        extract: isProduction,

        /**
         * 开启 CSS source maps
         * 开发环境下可以开启，方便调试
         * 生产环境关闭以提高性能
         */
        sourceMap: !isProduction,

        /**
         * CSS模块化配置
         * 在Vue CLI 4+中，CSS模块化的配置已更改
         * 默认情况下，*.module.css文件会被视为CSS模块
         * 如需在.vue文件中使用CSS模块化，可以在<style>标签上添加module属性
         */

        /**
         * css预设器配置项
         * 向CSS相关的loader传递选项
         */
        loaderOptions: {
            /**
             * sass配置
             * 全局引入变量和mixin，避免在每个文件中重复引入
             */
            sass: {
                // 全局引入变量和 mixin
                additionalData: `
          @use "@/styles/variables.scss" as *; // 全局变量
          @use "@/styles/mixins.scss" as *; // 全局混合
        `
            },
            // postcss配置已移至postcss.config.js文件中
        }
    },

    /**
     * 开发服务器配置
     * 控制开发环境下的服务器行为
     */
    devServer: {
        /**
         * 端口号
         * 开发服务器监听的端口
         */
        port: 8080,

        /**
         * 主机名
         * 开发服务器监听的主机名
         */
        host: '0.0.0.0',

        /**
         * 自动打开浏览器
         * 启动开发服务器时自动打开浏览器
         */
        open: false,

        /**
         * 热更新
         * 启用热模块替换，修改代码后无需刷新页面
         */
        hot: true,

        /**
         * 启用HTTPS
         * 是否使用HTTPS协议
         */
        https: false,

        /**
         * 显示警告和错误
         * 控制在浏览器中覆盖显示的错误和警告
         */
        client: {
            overlay: {
                warnings: false, // 不显示警告
                errors: true // 显示错误
            }
        },

        /**
         * 代理配置 - 解决跨域问题
         * 将特定URL的请求代理到指定服务器
         */
        proxy: {
            /**
             * 代理API请求
             * 将/api开头的请求代理到目标服务器
             */
            "/api": {
                target: "http://localhost:8069", // API服务器地址
                pathRewrite: {
                    "^/api": "" // 路径重写，移除/api前缀
                },
                changeOrigin: true, // 是否改变源，设为true会修改请求头中的host
                secure: false, // 是否验证SSL证书，设为false可接受无效证书
                /**
                 * 修改响应头信息
                 * 可以添加自定义响应头
                 */
                onProxyRes(proxyRes) {
                    // 添加跨域响应头
                    proxyRes.headers["Access-Control-Allow-Origin"] = "*";
                }
            }
        }
    },

    /**
     * PWA插件配置
     * 渐进式Web应用配置
     */
    pwa: {
        name: "小红书", // 应用名称
        themeColor: "#ff2442", // 主题颜色
        msTileColor: "#ff2442", // 微软磁贴颜色
        appleMobileWebAppCapable: "yes", // iOS是否可以添加到主屏幕
        appleMobileWebAppStatusBarStyle: "black", // iOS状态栏样式
        iconPaths: {
            favicon32: "favicon.ico", // 32x32 favicon
            favicon16: "favicon.ico", // 16x16 favicon
            appleTouchIcon: "favicon.ico", // iOS主屏图标
            maskIcon: "favicon.ico", // Safari固定标签页图标
            msTileImage: "favicon.ico" // Windows磁贴图标
        }
    },

    /**
     * 第三方插件配置
     * 配置Vue CLI插件的选项
     */
    pluginOptions: {
        /**
         * i18n国际化配置
         * 多语言支持配置
         */
        i18n: {
            locale: "zh-CN", // 默认语言
            fallbackLocale: "en", // 备用语言
            localeDir: "locales", // 语言文件目录
            enableInSFC: false // 是否在单文件组件中启用
        },
        // ...其他插件配置
    },

    /**
     * 是否为 Babel 或 TypeScript 使用 thread-loader
     * 多核CPU可以开启，提高编译速度
     */
    parallel: require("os").cpus().length > 1
});
